package com.knife.scheduler.infra.init;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.knife.common.utils.KnifeSpringUtil;
import com.knife.scheduler.config.KnifeSchedulerProperties;
import com.knife.scheduler.domain.entity.KnifeJobInfo;
import com.knife.scheduler.domain.service.KnifeJobService;
import com.knife.scheduler.infra.KnifeJobMarker;
import com.knife.scheduler.infra.annotations.KnifeJob;
import com.knife.scheduler.infra.constants.KnifeSchedulerConstant;
import com.knife.scheduler.infra.mapper.KnifeJobInfoMapper;
import com.knife.scheduler.infra.registry.KnifeJobRegistry;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 用于监听{@link com.knife.scheduler.infra.annotations.KnifeJob} 和 {@link KnifeJobMarker} 扫描定时任务
 *
 * @author： 76875
 * @date： 2022/4/1 星期五 18:51
 * @description：
 * @modifiedBy：
 * @version: 1.0
 */
@Component
@Order(1)
public class KnifeJobInit implements KnifeJobInitListener, CommandLineRunner, KnifeSchedulerConstant {

    public static final Logger LOGGER = LoggerFactory.getLogger(KnifeJobInit.class);


    @Autowired
    private KnifeJobService knifeJobService;

    @Autowired
    private KnifeSchedulerProperties knifeSchedulerProperties;

    @Resource
    private KnifeJobInfoMapper knifeJobInfoMapper;

    private void scanKnifeJob() throws SchedulerException {
        if (ObjectUtils.isEmpty(knifeSchedulerProperties.getExecutorFlag()) || !knifeSchedulerProperties.getExecutorFlag()) {
            LOGGER.info("本机不开启定时任务");
            return;
        }
        LOGGER.info("本机开启定时任务");
        Map<String, Object> map = KnifeSpringUtil.getApplicationContext().getBeansWithAnnotation(KnifeJob.class);
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            if (value instanceof KnifeJobMarker) {
                //KnifeJob annotation = ProxyUtils.getUserClass(KnifeJobMarker.class).getAnnotation(KnifeJob.class);
                KnifeJob annotation = value.getClass().getAnnotation(KnifeJob.class);
                if (ObjectUtils.isEmpty(annotation.code())) {
                    LOGGER.info(value.getClass().getSimpleName() + "KnifeJob注解code内容未定义");
                } else {
                    // 注册
                    KnifeJobRegistry.addJobHandler(annotation.code(), (KnifeJobMarker) value);
                    LambdaQueryWrapper<KnifeJobInfo> knifeJobInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    knifeJobInfoLambdaQueryWrapper.eq(KnifeJobInfo::getJobCode, annotation.code());
                    KnifeJobInfo knifeJobInfo = knifeJobInfoMapper.selectOne(knifeJobInfoLambdaQueryWrapper);
                    if (Objects.nonNull(knifeJobInfo)) {
                        boolean createJobFlag = true;
                        Date endDate = knifeJobInfo.getEndDate();
                        if (Objects.nonNull(endDate) && endDate.compareTo(new Date()) < 0) {
                            createJobFlag = false;
                        }
                        if (createJobFlag) {
                            knifeJobService.createJob(knifeJobInfo);
                        }
                    }
                }
            }
        }
    }


    @Override
    public void contextInitialized(ApplicationContext applicationContext) {
        // 扫描knife定时任务
        //try {
        //    this.scanKnifeJob();
        //} catch (SchedulerException e) {
        //    throw new CommonException("初始化调度任务失败", e);
        //}
    }

    @Override
    public void run(String... args) throws Exception {
        this.scanKnifeJob();
    }
}
